package com.jp.fm.servlet;

import static org.easymock.EasyMock.anyInt;
import static org.easymock.EasyMock.anyObject;
import static org.easymock.EasyMock.eq;
import static org.easymock.EasyMock.expect;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.easymock.EasyMock;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;

import com.jp.fm.EasyMockParent;
import com.jp.fm.dao.AccountDao;
import com.jp.fm.dao.BillReminderDao;
import com.jp.fm.dao.BudgetDao;
import com.jp.fm.dao.CategoryDao;
import com.jp.fm.data.Account;
import com.jp.fm.data.BillReminder;
import com.jp.fm.data.Budget;
import com.jp.fm.data.Category;
import com.jp.fm.service.BudgetService;
import com.jp.fm.service.CategoryService;
import com.jp.fm.service.PageService;
import com.jp.fm.service.TransactionService;

public class ShowAccountSummaryTest extends EasyMockParent {

	private ShowAccountSummary servlet = null;

	private HttpServletRequest mockRequest = null;
	private HttpServletResponse mockResponse = null;
	private AccountDao mockAccountDao = null;
	private CategoryDao mockCategoryDao = null;
	private BudgetDao mockBudgetDao = null;
	private BillReminderDao mockBillReminderDao = null;
	private TransactionService mockTransactionService = null;
	private CategoryService mockCategoryService = null;
	private BudgetService mockBudgetService = null;
	private PageService mockPageService = null;
	private RequestDispatcher mockRequestDispatcher = null;

	@BeforeClass
	public static void setUpBeforeClass() throws Exception {
	}

	@AfterClass
	public static void tearDownAfterClass() throws Exception {
	}

	@Before
	public void setUp() throws Exception {
		super.setUp();

		servlet = new ShowAccountSummary();
	}

	@After
	public void tearDown() throws Exception {
		super.tearDown();
	}

	@Test
	public final void testComposeBudgets() {

		List<String> alerts = new ArrayList<String>();
		List<Budget> budgetList = new ArrayList<Budget>();

		servlet.setAccountDao(mockAccountDao);
		servlet.setBudgetDao(mockBudgetDao);
		servlet.setCategoryDao(mockCategoryDao);
		servlet.setBudgetService(mockBudgetService);
		servlet.setCategoryService(mockCategoryService);
		servlet.setPageService(mockPageService);
		servlet.setTransactionService(mockTransactionService);

		expect(
				mockBudgetService.findBudgetList(anyObject(Date.class),
						anyObject(Date.class), eq(alerts))).andReturn(
				budgetList);
		mockBudgetDao.copyBudgetsFromLastMonth();
		EasyMock.expectLastCall();
		expect(
				mockBudgetService.findBudgetList(anyObject(Date.class),
						anyObject(Date.class), eq(alerts))).andReturn(null);
		mockRequest.setAttribute("budgetList", null);
		EasyMock.expectLastCall();

		replayMocks();

		servlet.composeBudgets(mockRequest, alerts);
	}

	@Test
	public final void testComposeTopCategories() {
		servlet.setAccountDao(mockAccountDao);
		servlet.setBudgetDao(mockBudgetDao);
		servlet.setCategoryDao(mockCategoryDao);
		servlet.setBudgetService(mockBudgetService);
		servlet.setCategoryService(mockCategoryService);
		servlet.setPageService(mockPageService);
		servlet.setTransactionService(mockTransactionService);

		Map<Float, Category> topCatMap = new HashMap<Float, Category>();

		expect(
				mockCategoryService.getTopCategoriesOverTimeFrame(
						anyObject(Date.class), anyObject(Date.class)))
				.andReturn(topCatMap);
		expect(
				mockCategoryService.getTopCategoriesOverTimeFrame(
						anyObject(Date.class), anyObject(Date.class)))
				.andReturn(topCatMap);
		mockRequest.setAttribute(eq("topCategoriesThisMonth"),
				anyObject(Map.class));
		mockRequest.setAttribute(eq("topCategories"), anyObject(Map.class));

		replayMocks();

		servlet.composeTopCategories(mockRequest);
	}

	@Test
	public final void testComposeBills() {

		servlet.setAccountDao(mockAccountDao);
		servlet.setBudgetDao(mockBudgetDao);
		servlet.setCategoryDao(mockCategoryDao);
		servlet.setBillReminderDao(mockBillReminderDao);
		servlet.setBudgetService(mockBudgetService);
		servlet.setCategoryService(mockCategoryService);
		servlet.setPageService(mockPageService);
		servlet.setTransactionService(mockTransactionService);

		List<BillReminder> list = new ArrayList<BillReminder>();
		list.add(new BillReminder(null, null, null, null, new Date(), null));

		expect(mockBillReminderDao.findByDueDateAndRange(anyInt())).andReturn(
				list);
		mockRequest.setAttribute(eq("bills"), anyObject(BillReminder.class));
		EasyMock.expectLastCall();
		expect(mockBillReminderDao.findAll()).andReturn(list);
		mockRequest.setAttribute(eq("allBills"), anyObject(BillReminder.class));
		EasyMock.expectLastCall();
		replayMocks();

		servlet.composeBills(mockRequest);
	}

	@Test
	public final void testComposeAlerts() {

		List<String> alerts = new ArrayList<String>();

		servlet.setAccountDao(mockAccountDao);
		servlet.setBudgetDao(mockBudgetDao);
		servlet.setCategoryDao(mockCategoryDao);
		servlet.setBudgetService(mockBudgetService);
		servlet.setCategoryService(mockCategoryService);
		servlet.setPageService(mockPageService);
		servlet.setTransactionService(mockTransactionService);

		expect(mockTransactionService.findUncategorizedTransactions())
				.andReturn(alerts);
		expect(mockTransactionService.findFeeTransactions()).andReturn(alerts);
		expect(mockPageService.findAccountAlerts()).andReturn(alerts);
		expect(mockPageService.findCreditAlerts()).andReturn(alerts);
		expect(mockTransactionService.findUnconfirmedTransactions()).andReturn(
				alerts);
		mockRequest.setAttribute("alerts", alerts);
		EasyMock.expectLastCall();

		replayMocks();

		servlet.composeAlerts(mockRequest, alerts);
	}

	@Test
	public final void testDoPostSuccess() throws ServletException, IOException {

		Class[] args = { HttpServletRequest.class, HttpServletResponse.class };

		ShowAccountSummary partialMockServlet = (ShowAccountSummary) createPartialMock(
				ShowAccountSummary.class, "doPost", args, false);

		partialMockServlet.setAccountDao(mockAccountDao);
		partialMockServlet.setBudgetDao(mockBudgetDao);
		partialMockServlet.setCategoryDao(mockCategoryDao);
		partialMockServlet.setBudgetService(mockBudgetService);
		partialMockServlet.setCategoryService(mockCategoryService);
		partialMockServlet.setPageService(mockPageService);
		partialMockServlet.setTransactionService(mockTransactionService);

		List<Account> accts = new ArrayList<Account>();
		Set<Category> cats = new TreeSet<Category>();
		List<String> alerts = new ArrayList<String>();

		mockPageService.composeRequestLeftNav(mockRequest);
		EasyMock.expectLastCall();
		expect(mockAccountDao.findAll()).andReturn(accts);
		mockRequest.setAttribute("allAccounts", accts);
		expect(mockCategoryDao.findAll()).andReturn(cats);
		mockRequest.setAttribute("allCategories", cats);
		EasyMock.expectLastCall();
		partialMockServlet.composeBills(mockRequest);
		EasyMock.expectLastCall();
		partialMockServlet.composeBudgets(mockRequest, alerts);
		EasyMock.expectLastCall();
		partialMockServlet.composeTopCategories(mockRequest);
		EasyMock.expectLastCall();
		partialMockServlet.composeAlerts(mockRequest, alerts);
		EasyMock.expectLastCall();
		expect(mockRequest.getRequestDispatcher(anyObject(String.class)))
				.andReturn(mockRequestDispatcher);
		mockRequestDispatcher.forward(mockRequest, mockResponse);
		EasyMock.expectLastCall();

		replayMocks();
		EasyMock.replay(partialMockServlet);

		partialMockServlet.doPost(mockRequest, mockResponse);

		EasyMock.verify(partialMockServlet);
	}

}
